home *** CD-ROM | disk | FTP | other *** search
- {
- SEAN PALMER
-
- I was just toying around With a B-Spline curve routine I got out of an
- old issue of Byte, and thought it was pretty neat. I changed it to use
- fixed point fractions instead of Reals, and optimized it some...
-
- by Sean Palmer
- public domain
- }
-
- Var
- color : Byte;
- Procedure plot(x, y : Word);
- begin
- mem[$A000 : y * 320 + x] := color;
- end;
-
- Type
- coord = Record
- x, y : Word;
- end;
-
- CurveDataRec = Array [0..65521 div sizeof(coord)] of coord;
-
- Function fracMul(f, f2 : Word) : Word;
- Inline(
- $58/ {pop ax}
- $5B/ {pop bx}
- $F7/$E3/ {mul bx}
- $89/$D0); {mov ax,dx}
-
- Function mul(f, f2 : Word) : LongInt;
- Inline(
- $58/ {pop ax}
- $5B/ {pop bx}
- $F7/$E3); {mul bx}
-
-
- Const
- nSteps = 1 shl 8; {about 8 For smoothness (dots), 4 For speed (lines)}
-
- Procedure drawBSpline(Var d0 : coord; nPoints : Word);
- Const
- nsa = $10000 div 6;
- nsb = $20000 div 3;
- step = $10000 div nSteps;
- Var
- i, xx, yy,
- t1, t2, t3,
- c1, c2, c3, c4 : Word;
-
- d : curveDataRec Absolute d0;
-
- begin
- t1 := 0;
- color := 32 + 2;
-
- For i := 0 to nPoints - 4 do
- begin
-
- {algorithm converted from Steve Enns' original Basic subroutine}
-
- Repeat
- t2 := fracMul(t1, t1);
- t3 := fracMul(t2, t1);
- c1 := (Integer(t2 - t1) div 2) + nsa - fracmul(nsa, t3);
- c2 := (t3 shr 1) + nsb - t2;
- c3 := ((t2 + t1 - t3) shr 1) + nsa;
- c4 := fracmul(nsa, t3);
- xx := (mul(c1, d[i].x) + mul(c2, d[i + 1].x) +
- mul(c3, d[i + 2].x) + mul(c4, d[i + 3].x)) shr 16;
- yy := (mul(c1, d[i].y) + mul(c2, d[i + 1].y) +
- mul(c3, d[i + 2].y) + mul(c4, d[i + 3].y)) shr 16;
- plot(xx, yy);
- inc(t1, step);
- Until t1 = 0; {this is why nSteps must be even power of 2}
- inc(color);
- end;
- end;
-
- Const
- pts = 24; {number of points} {chose this because of colors}
-
- Var
- c : Array [-1..2 + pts] of coord;
- i : Integer;
- begin
- Asm
- mov ax, $13
- int $10
- end; {init vga/mcga Graphics}
- randomize;
- For i := 1 to pts do
- With c[i] do
- begin
- {x:=i*(319 div pts);} {for precision demo}
- x := random(320); {for fun demo}
- y := random(200);
- end;
- {for i:=1 to pts div 2 do c[i*2+1].y:=c[i*2].y;} {fit closer}
- For i := 1 to pts do
- With c[i] do
- begin
- color := i + 32;
- plot(x, y);
- end;
- {replicate end points so curves fit to input}
- c[-1] := c[1];
- c[0] := c[1];
- c[pts + 1] := c[pts];
- c[pts + 2] := c[pts];
- drawBSpline(c[-1], pts + 4);
- readln;
- Asm
- mov ax, 3
- int $10
- end; {Text mode again}
- end.